// uvm_tb/pkg/binary_alu_transaction.sv
`ifndef BINARY_ALU_TRANSACTION_SV
`define BINARY_ALU_TRANSACTION_SV

// import uvm_pkg::*;
// `include "uvm_macros.svh"

// Forward declaration of data types if they are in a package
// `include "/home/jiangcx/Desktop/LPU/rtl/include/dtype.svh" 

class binary_alu_transaction extends uvm_sequence_item;
    // ========================================================================
    // Data Members
    // ========================================================================

    // Configuration
    rand logic     [2:0] mode;
    rand bf16_t          scalar;

    // Input Payloads
    rand aru_dat_t       top_data;
    rand aru_dat_t       left_data;
    rand aru_dat_t       bottom_data;

    // Input SDB (Sideband Data)
    rand aru_sdb_t       top_sdb;
    rand aru_sdb_t       left_sdb;
    rand aru_sdb_t       bottom_sdb;

    // Expected Output
    aru_dat_t            expected_data;
    aru_sdb_t            expected_sdb;

    // Control flags for the driver
    rand bit             send_top;
    rand bit             send_left;
    rand bit             send_bottom;
    int                  fpu_latency    = 0;  // Expected latency for this transaction

    // ========================================================================
    // UVM Macros
    // ========================================================================
    `uvm_object_utils_begin(binary_alu_transaction)
        `uvm_field_int(mode, UVM_ALL_ON)
        `uvm_field_int(scalar, UVM_ALL_ON)



    // Using string to avoid deep copy issues with unpacked arrays in some simulators
    // `uvm_field_object(top_data, UVM_ALL_ON) 
    `uvm_object_utils_end

    // ========================================================================
    // Constructor
    // ========================================================================
    function new(string name = "binary_alu_transaction");
        super.new(name);
    endfunction

    // ========================================================================
    // Constraints
    // ========================================================================
    constraint c_mode {mode inside {0, 1, 2, 3, 4};}

    // Default: send all inputs (can be overridden in inline constraints)
    // Use 'soft' to allow inline constraints to override
    constraint c_send_defaults {
        soft send_top == 1;
        soft send_left == 1;
        soft send_bottom == 1;
    }

    // ========================================================================
    // Pre/Post Body for calculating expected results
    // ========================================================================
    function void pre_randomize();
        // Default SDB values
        top_sdb    = '{vld_m: 8, vld_n: 8, eom: 1'b1, eon: 1'b1};
        left_sdb   = '{vld_m: 8, vld_n: 8, eom: 1'b1, eon: 1'b1};
        bottom_sdb = '{vld_m: 8, vld_n: 8, eom: 1'b1, eon: 1'b1};
    endfunction

    function void post_randomize();
        // Based on the mode, calculate the expected output
        case (mode)
            0: begin  // Top Bypass
                expected_data = top_data;
                expected_sdb  = top_sdb;
                fpu_latency   = 2;  // Minimal bypass latency
            end
            1: begin  // Bottom Bypass
                expected_data = bottom_data;
                expected_sdb  = bottom_sdb;
                fpu_latency   = 2;
            end
            2: begin  // Left Bypass
                expected_data = left_data;
                expected_sdb  = left_sdb;
                fpu_latency   = 2;
            end
            3: begin  // Top * Bottom
                for (int i = 0; i < `P_ARU * `N0; i++) begin
                    // This requires a BF16 reference model
                    // expected_data.dat[i] = bf16_multiply(top_data.dat[i], bottom_data.dat[i]);
                end
                expected_sdb = top_sdb;  // Or based on logic
                fpu_latency  = 15;  // Example latency for MUL
            end
            4: begin  // Scalar * Bottom
                for (int i = 0; i < `P_ARU * `N0; i++) begin
                    // expected_data.dat[i] = bf16_multiply(scalar, bottom_data.dat[i]);
                end
                expected_sdb = bottom_sdb;
                fpu_latency  = 15;
            end
        endcase
    endfunction

endclass : binary_alu_transaction

`endif  // BINARY_ALU_TRANSACTION_SV
